<template>
  <view class="item">
    <!-- 当前节点行 -->
    <view class="node-row" :style="{ marginLeft: level * indent + 'px' }">
      <view class="node-content">
        <view
          class="expand-icon"
          @click="toggle"
          :class="{
            'expand-collapsed': hasChildren && !isExpanded,
            'expand-expanded': hasChildren && isExpanded,
            'expand-none': !hasChildren
          }"
        ></view>

        <view class="x-f cellItem" @click="choiceCell(node)" :class="{ 'is-active': isSelected }">
          <uni-icons fontFamily="CustomFontPlatform" color="#409eff" :size="14">
            {{ $utils.toUniCode('&#xe782;') }}
          </uni-icons>

          <text class="label" v-html="highlightedLabel"></text>
        </view>
      </view>
    </view>

    <!-- 子节点（懒加载，保留样式） -->
    <view v-if="hasChildren && isExpanded">
      <view v-for="child in node.children" :key="child.id">
        <m-tree-node
          :node="child"
          :level="level + 1"
          :selected-id="selectedId"
          :search-value="searchValue"
          :search-key="searchKey"
          @update:selectedId="onSelected"
        />
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'm-tree-node',
  props: {
    node: {
      type: Object,
      required: true
    },
    level: {
      type: Number,
      required: true
    },
    selectedId: {
      type: [String, Number],
      default: ''
    },
    searchValue: {
      type: String,
      default: ''
    },
    searchKey: {
      type: String,
      default: 'label'
    }
  },
  data() {
    return {
      indent: 20
    }
  },
  computed: {
    hasChildren() {
      return this.node.children && this.node.children.length > 0
    },
    isSelected() {
      return this.selectedId === this.node.id
    },
    isExpanded() {
      return this.node._expanded !== false
    },
    highlightedLabel() {
      const text = this.node[this.searchKey] || ''
      if (!this.searchValue) return text

      const escapedKeyword = this.searchValue.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
      const reg = new RegExp(escapedKeyword, 'gi')
      return text.replace(reg, match => `<span style="color: #007aff;">${match}</span>`)
    }
  },
  methods: {
    toggle() {
      if (this.hasChildren) {
        this.$set(this.node, '_expanded', !this.isExpanded)
      }
    },
    choiceCell(node) {
      this.$emit('update:selectedId', node.id)
    },
    onSelected(id) {
      this.$emit('update:selectedId', id)
    }
  }
}
</script>

<style scoped lang="scss">
.item {
  position: relative;
}

.node-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  min-height: 30px;
}

.node-content {
  display: flex;
  align-items: center;
  flex-direction: row;
  position: relative;

  &::before {
    content: '|';
    width: 1px;
    height: 100px;
    position: absolute;
    top: -10px;
    left: 10px;
    color: #d3d7d7;
  }
}

.expand-icon {
  width: 30px;
  height: 30px;
  background-image: url('/uni_modules/mc-ui/static/image/32px.png');
  background-repeat: no-repeat;
  background-size: auto;
  margin-right: 5px;
}

.expand-collapsed {
  background-position: -100px 0px;
}

.expand-expanded {
  background-position: -132px 0px;
}

.expand-none {
  background-position: -68px 0px;
}

.cellItem {
  padding: 2px 4px;
  border-radius: 4px;
}

.label {
  font-size: 12px;
  color: #707478;
  margin-left: 4px;
}

.is-active {
  background-color: #ffbab9;
}
</style>
